package com.kabu.aqs;

import sun.misc.Unsafe;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.LockSupport;

/**
 * @author jiawuwei
 * @Copyright:
 * @date 2020/7/31,14:26
 */
public class AQSLock {
    public final static int STATE_UNLOCK = 0;
    public final static int STATE_LOCK = 1;
    private volatile int state = STATE_UNLOCK; //同步器
    private Thread lockHolder; //持有同步器的线程
    private ConcurrentLinkedQueue<Thread> waiters = new ConcurrentLinkedQueue();//阻塞队列，获取不到锁的进入阻塞队列
    private static final Unsafe unsafe = UnsafeInstance.reflectGetUnsafe();
    private static long stateOffset;

    static {
        try {
            //对象头中state字段的偏移量，对象头数据接口为 markword(8)+classpointer(4)+data+补齐字节，必须是8的整数倍
            stateOffset = unsafe.objectFieldOffset(AQSLock.class.getDeclaredField("state"));
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    public int getState() {
        return state;
    }

    public AQSLock setState(int state) {
        this.state = state;
        return this;
    }

    public Thread getLockHolder() {
        return lockHolder;
    }

    public AQSLock setLockHolder(Thread lockHolder) {
        this.lockHolder = lockHolder;
        return this;
    }

    /**
     * 加锁
     */
    public void lock() {
        //判断同步器是否被持有
        if (acquire()) {
            return;
        }
        Thread current = Thread.currentThread();
        //没有获取到锁的加入队列
        waiters.add(current);
        //然后自旋阻塞等待被唤醒
        for (; ; ) {
            //只有头部才可以抢锁
            if (current == waiters.peek() && acquire()) {
                //获取到锁后出队列
                waiters.poll();
                return;
            }
            //阻塞当前线程
            LockSupport.park(current);
        }
    }

    /**
     * 获取锁
     *
     * @param current
     */
    private boolean acquire() {
        Thread current = Thread.currentThread();
        int c = getState();
        //c==0 说明还没有人持有同步器
        if (c == STATE_UNLOCK) {
            //（获取队列为空或者为队首）&& 没有被修改过
            if ((waiters.size() == 0 || waiters.peek() == current) && compareAndSwapState(STATE_UNLOCK, STATE_LOCK)) {
                setLockHolder(current);
                return true;
            }
        }
        return false;
    }

    /**
     * 解锁
     */
    public void unlock() {
        //如果当前线程不是持有同步器的线程
        if (Thread.currentThread() != lockHolder) {
            throw new RuntimeException("lockholder is not current thread!");
        }
        //修改同步器状态
        int state = getState();
        if (compareAndSwapState(state, STATE_UNLOCK)) {
            setLockHolder(null);
            //唤醒队首元素
            Thread peek = waiters.peek();
            if (peek != null) {
                LockSupport.unpark(peek);
                System.out.println("阻塞队列大小："+waiters.size());
            }
        }
    }

    /**
     * 原子化修改state值
     *
     * @param expect
     * @param update
     * @return
     */
    public final boolean compareAndSwapState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }
}
